#include "functionhandle.h"

void idle_func(void);


/**
 * @method register a new task
 * @for run in main
 * @param priority:the biger the higher  period:n ms
 * @return 
 */
uint32_t func_reg(struct SFUNH_ *thiss,fun_p func,uint32_t priority,uint32_t period)
{
    if(thiss->ifuncp_count<TASKCNTMAX)
    {
        thiss->sfuncp[thiss->ifuncp_count].funp = func;
        thiss->sfuncp[thiss->ifuncp_count].priority = priority;
        thiss->sfuncp[thiss->ifuncp_count].isready = 0;
        thiss->sfuncp[thiss->ifuncp_count].period = period;
        thiss->ifunc_period[thiss->ifuncp_count] = period;
        thiss->ifunc_delay[thiss->ifuncp_count] = 0;
        thiss->runcnt[thiss->ifuncp_count] = 0;
        thiss->runcntmax[thiss->ifuncp_count] = 0;
        return thiss->ifuncp_count++;
    }
    else
    {
        return 0;
    }
}

void func_handle(SFUNH *thiss)
{
    uint32_t cnt;
    static uint32_t static_last_cnt = 0;
    uint8_t fun_to_run = 0;
    for(cnt = 0;cnt <thiss->ifuncp_count ;cnt ++)
    {
        if(thiss->sfuncp[static_last_cnt].isready == 1 && thiss->sfuncp[fun_to_run].priority< thiss->sfuncp[static_last_cnt].priority)//�������ȼ������ĳ���
        {
            fun_to_run = static_last_cnt;
            break;
        }
        static_last_cnt += 1;
        //��ֹ���Ǵ��㿪ʼ ��ֹ��ͬ���ȼ�����������ִ�в���
        static_last_cnt = static_last_cnt%thiss->ifuncp_count;
    }
    //printf("frun=%d\n", fun_to_run);
    thiss->sfuncp[fun_to_run].funp();//tiao dao lun dao de hanshu
    //printf("fout");
    thiss->ifunc_period[fun_to_run] = thiss->sfuncp[fun_to_run].period;//shua xin chao shi
    thiss->sfuncp[fun_to_run].isready = 0;//chong zhi zhuang tai
    thiss->runcnt[fun_to_run]++;
}

void func_time_handle_1ms(SFUNH *thiss)
{
    uint32_t cnt;
    static uint32_t mscnt = 0;
    for(cnt = 0;cnt <thiss->ifuncp_count ;cnt ++)
    {
        if(thiss->ifunc_period[cnt] > 1 )
        {
            thiss->ifunc_period[cnt] --;
        }
        else if(thiss->ifunc_period[cnt] == 1)
        {
            thiss->sfuncp[cnt].isready = 1;
            thiss->ifunc_period[cnt] = 0;
        }
        if(thiss->ifunc_delay[cnt] > 1 )//jian dao 1 run 0 ign
        {
            thiss->ifunc_delay[cnt] --;
        }
        else if(thiss->ifunc_delay[cnt] == 1)
        {
            thiss->sfuncp[cnt].isready = 1;
            thiss->ifunc_delay[cnt] = 0;
        }
    }
    mscnt = (mscnt+1)%1000;
    if(mscnt==0)
    {
        //每秒钟统计一次各任务的运行次数
        for(cnt = 0;cnt <thiss->ifuncp_count ;cnt ++)
        {
           thiss->runcntmax[cnt] =  thiss->runcnt[cnt];
           thiss->runcnt[cnt]=0;
        }
    }
}

void func_idle(void)
{
    
}

void func_setready(struct SFUNH_ *thiss,FUNCID funcid)
{
    thiss->sfuncp[funcid].isready = 1;
}

void func_setdelay(struct SFUNH_ *thiss,FUNCID funcid,uint32_t delay)
{
    thiss->ifunc_delay[funcid] = delay;
}

void func_setperiod(struct SFUNH_ *thiss,FUNCID funcid,uint32_t peroid)
{
    thiss->sfuncp[funcid].period = peroid;
    thiss->ifunc_period[funcid] = peroid;
}

void func_waithere(struct SFUNH_ *thiss,FUNCID funcid,uint32_t timeout)
{
    thiss->sfuncp[funcid].isready = 0;
    thiss->ifunc_delay[funcid] = timeout;
    while(thiss->sfuncp[funcid].isready == 0)
    {
        thiss->func_handle(&sfunchandle);
    }
}

void newsfunh(SFUNH *thiss)
{
    //xian tian jia 1 ge idle function
    thiss->sfuncp[thiss->ifuncp_count].funp = &func_idle; //idle task
    thiss->sfuncp[thiss->ifuncp_count].priority = 0; //min priority
    thiss->sfuncp[thiss->ifuncp_count].isready = 1;
    thiss->ifuncp_count++;
}

SFUNH sfunchandle = {
    .func_handle = &func_handle,
    .func_reg = &func_reg,
    .func_time_handle_1ms = &func_time_handle_1ms,
    .func_setready = &func_setready,
    .func_setdelay = &func_setdelay,
    .func_setperiod = &func_setperiod,
    .func_waithere = &func_waithere
};
